import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Created by LuoTao on 2016/10/25.
 * LemonTech Copyright reserved.
 */
public class monitor {

    private static Logger logger = LogManager.getLogger(monitor.class);
    private ExecutorService queryPool = Executors.newFixedThreadPool(10);
    private Map<query, Table> queryResult = new HashMap<>();

    public void run(MonitorConfig monitorConfig) {
        //遍历所有数据库
        final Map<Config, Connection> allConnections = new HashMap<>();
        for (final Config dbConfig : monitorConfig.getConfigList()) {
            Connection conn = DBHelper.getConnection(dbConfig);
            allConnections.put(dbConfig, conn);
            //遍历所有查询
            for (final query m_query : dbConfig.getQueryList()) {
                final String queryname = m_query.getName();
                queryPool.submit(new Runnable() {
                    @Override
                    public void run() {
                        Table m_resultTable = processSQL(allConnections.get(dbConfig), queryname, m_query.getSql(dbConfig));
                        //如果需要转置
                        if (m_query.getNeedTranspose() != null) {
                            if (m_query.getNeedTranspose()) {
                                m_resultTable = m_resultTable.Transpose(queryname);
                            }
                        }
                        //如果需要重命名
                        if (m_query.getTranslate() != null) {
                            m_resultTable.Translate(m_query.getTranslate());
                        }
                        queryResult.put(m_query, m_resultTable);
                    }
                });
            }
        }
        queryPool.shutdown();
        try {
            queryPool.awaitTermination(30, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (Connection connection : allConnections.values()) {
            try {
                connection.close();
            } catch (SQLException e) {
                logger.warn(connection.toString() + "连接关闭失败");
                e.printStackTrace();
            }
        }
        logger.info("所有数据查询完毕，开始写入PDF文件");
        PDFHelper write2PDF = new PDFHelper();
        write2PDF.write(monitorConfig.getReportName() + ".pdf", monitorConfig, queryResult);
        logger.info("PDF文件写入完成");

    }

    /**
     * 在指定连接中执行指定语句，并生成结果表格
     *
     * @param connection 连接
     * @param sql        sql语句
     */
    public Table processSQL(Connection connection, String queryName, String sql) {
        long startTime = System.currentTimeMillis();
        Table resultTable = new Table();
        logger.info(queryName + "开始查询");
        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            ResultSet rs = pstmt.executeQuery();
            Boolean isFirst = true;
            int colLength = 0;
            while (rs.next()) {
                if (isFirst) {
                    ResultSetMetaData rsmd = rs.getMetaData();
                    colLength = rsmd.getColumnCount();
                    String[] header = new String[colLength];
                    for (int i = 0; i < colLength; i++) {
                        header[i] = rsmd.getColumnLabel(i + 1);
                    }
                    resultTable.initHeader(header);
                    isFirst = false;
                }
                String[] row = new String[colLength];
                for (int i = 0; i < colLength; i++) {
                    row[i] = rs.getString(i + 1);
                }
                resultTable.insertRow(row);
            }
            long endTime = System.currentTimeMillis();
            logger.info(queryName + "查询成功 花费" + (endTime - startTime) + "ms");
        } catch (SQLException e) {
            logger.error(queryName + "查询失败：" + e.getMessage());
            e.printStackTrace();
        }
        return resultTable;
    }

}
